package com.wrupple.vegetate.server.bussiness;

import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;
import javax.jdo.Query;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.wrupple.muba.common.domain.FilterCriteria;
import com.wrupple.muba.common.domain.FilterData;
import com.wrupple.muba.common.domain.FilterDataOrdering;

public final class PMF {
	private static final PersistenceManagerFactory pmfInstance = JDOHelper
			.getPersistenceManagerFactory("transactions-optional");
	protected final static Log logger = LogFactory.getLog(PersistenceManagerFactory.class);

	private PMF() {
	}

	public static PersistenceManagerFactory get() {
		return pmfInstance;
	}

	/**
	 * Adds filter values to a query
	 * 
	 * @param query
	 *            the opened query
	 * @param aditionalFilters
	 * @param filter
	 *            a map where keys are parameter names mapped to their
	 *            respective values values
	 */
	public static void setQueryCriteria(Query query, FilterData criteria, String aditionalFilters) {
		if (criteria == null) {
			return;
		}
		if (criteria.isConstrained()) {
			query.setRange(criteria.getStart(), criteria.getEnd());
		}
		StringBuilder filterList ;
		if (criteria.getOrder() != null) {
			filterList = new StringBuilder(criteria.getOrder().size() * 20);
			for (FilterDataOrdering order : criteria.getOrder()) {
				filterList.append(order.getField());
				filterList.append(' ');
				if (order.isAscending()) {
					filterList.append("ascending");
				} else {
					filterList.append("descending");
				}
			}
			if (filterList.length() > 0) {
				String ordering = filterList.substring(0, filterList.length() - 1);
				query.setOrdering(ordering);
			}
		}
		
		Map<String, List<FilterCriteria>> filter = criteria.getFilters();
		if (filter.size() == 0) {
			if (aditionalFilters != null) {
				query.setFilter(aditionalFilters);
			}
			return;
		}
		int buffersize = filter.size() * 25;
		if (aditionalFilters != null) {
			buffersize += aditionalFilters.length();
		}
		filterList = new StringBuilder(buffersize);
		Set<String> params = filter.keySet();

		// create parameter list
		if (aditionalFilters != null) {
			filterList.append('(');
			filterList.append(aditionalFilters);
			filterList.append(")");
			filterList.append(" && ");
		}

		List<FilterCriteria> temp;
		int count = 0;
		int paramCount = 0;
		for (String param : params) {
			temp = filter.get(param);

			if (temp != null && temp.size() > 0) {
				/*
				 * Filter declaration
				 */
				filterList.append("(");
				count = 0;
				List<String> values;
				String operator;
				for (FilterCriteria filterCriteria : temp) {
					values = filterCriteria.getValues();
					operator = filterCriteria.getOperator();
					
					String value;
					for(int i = 0 ; i< values.size(); i++){
						value = values.get(i);
						filterList.append(param);
						filterList.append(operator);

						try {
							filterList.append(Long.parseLong(value));
						} catch (NumberFormatException e) {
							try {
								filterList.append(Double.parseDouble(value));
							} catch (NumberFormatException o) {
								if("null".equals(value)){
									filterList.append("null");
								}else{
									filterList.append('\"');
									filterList.append(value.replace('\"', ' ').replace('\'', ' '));
									filterList.append('\"');
								}
								
							}
						}
						
						if (i < values.size() - 1) {
							if (FilterData.EQUALS.equals(operator)) {
								filterList.append(" || ");
							} else {
								filterList.append(" && ");

							}
						}
						
					}

					if (count < temp.size() - 1) {
						if (FilterData.EQUALS.equals(operator)) {
							filterList.append(" || ");
						} else {
							filterList.append(" && ");

						}
					}
					count++;
				}
				filterList.append(")");
				
				if (paramCount < params.size() - 1) {
					filterList.append(" && ");
				}
				
				paramCount++;
			}

		}
		String filterString = filterList.toString();
		// set Data
		query.setFilter(filterString);

		

	}
}